package com.demo.spring.Value注解底层演示;

import java.lang.reflect.Field;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.stereotype.Component;

@Configuration
public class Test {
	
	public static void main(String[] args) throws Exception {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Test.class);
		DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
		
		ContextAnnotationAutowireCandidateResolver resolver = new ContextAnnotationAutowireCandidateResolver();
		resolver.setBeanFactory(beanFactory);
		
		Field field = Bean1.class.getDeclaredField("name");
		field.setAccessible(true);
		DependencyDescriptor dd1 = new DependencyDescriptor(field, true);
		String value = resolver.getSuggestedValue(dd1).toString();
		System.out.println(value);
		
		// 解析${}
		value = context.getEnvironment().resolvePlaceholders(value);
		System.out.println(value);
		
		Field age = Bean1.class.getDeclaredField("age");
		age.setAccessible(true);
		DependencyDescriptor dd2 = new DependencyDescriptor(age, true);
		value = resolver.getSuggestedValue(dd2).toString();
		System.out.println(value);
		
		value = context.getEnvironment().resolvePlaceholders(value);
		// 类型转换
		int value2 = context.getBeanFactory().getTypeConverter().convertIfNecessary(value, int.class);
		System.out.println(value2);
		
		Field bean3f = Bean1.class.getDeclaredField("bean3");
		bean3f.setAccessible(true);
		DependencyDescriptor dd3 = new DependencyDescriptor(bean3f, true);
		value = resolver.getSuggestedValue(dd3).toString();
		System.out.println(value);
		
		// 解析#{}，即SPEL
		Object bean3 = context.getBeanFactory().getBeanExpressionResolver().evaluate(value, new BeanExpressionContext(beanFactory, null));
		System.out.println(bean3);
	}
	
	public class Bean1 {
		@Value("${JAVA_HOME}")
		private String name;
		@Value("18")
		private int age;
		@Value("#{@bean3}")
		private Bean3 bean3;
	}
	
	@Component("bean3")
	public class Bean3 {
		
	}

}
